package knapsack;

import java.util.ArrayList;
import java.util.Random;

import evo.Evolution;
import evo.IInstance;

public class Run {

	
	public static void main(String[] args)
	{
		int size = 20;
		int max = 100;
		int generations = 20;
		int population = 100;
		Random r = new Random();
		
		// constant problem
		int[] weights = new int[] {67,71,49,30,24,17,84,77,25,49,19,56,60,71,84,87,30,97,20,14};
		int[] values = new int[] {74,12,20,41,64,78,35,14,46,42,71,91,23,62,70,44,31,63,11,89};
		
		
		// random problem
		/*
		int[] weights = new int[size];
		int[] values = new int[size];
		for (int i = 0; i < size; i++) {
			weights[i] = r.nextInt(max);
			values[i] = r.nextInt(max);
		}
		*/
		KnapsackProblem prob = new KnapsackProblem(weights, values, 100);
		KnapsackBuilder builder = new KnapsackBuilder(prob);
		double pmutate = 0.1;
		double clonePart = 0.3;
		
		
		Evolution evo = new Evolution(builder, population, pmutate, clonePart);

		for (int i = 0; i < generations; i++) {
			System.out.println("generation "+i+" best fitness: "+getBestFitness(evo.getCurrentGen()));
			evo.advanceGen();
		}
		printSolution(evo.getCurrentGen());
	}
	
	
	private static int getBestFitnessIndex(ArrayList<IInstance> gen)
	{
		int besti = 0;
		for (int i = 0; i < gen.size(); i++) {
			if (gen.get(i).getFitness() > gen.get(besti).getFitness())
			{
				besti = i;
			}
		}
		return besti;
	}
	
	private static double getBestFitness(ArrayList<IInstance> gen)
	{
		int besti = 0;
		for (int i = 0; i < gen.size(); i++) {
			if (gen.get(i).getFitness() > gen.get(besti).getFitness())
			{
				besti = i;
			}
		}
		return gen.get(besti).getFitness();
	}
	
	
	
	private static void printSolution(ArrayList<IInstance> gen)
	{
		int besti = getBestFitnessIndex(gen);
		KnapsackSolution sol = (KnapsackSolution)gen.get(besti);
		int valsum = 0;
		int weightsum = 0;
		for (int i = 0; i < sol.itemsTaken.length; i++) {
			if (sol.itemsTaken[i])
			{
				valsum += sol.prob.values[i];
				weightsum += sol.prob.weights[i];
				System.out.println("item: "+i+", weight: "+sol.prob.weights[i]+", value: "+sol.prob.values[i]);
			}
		}
		System.out.println("total weight: "+weightsum+", total value: "+valsum);
		System.out.println("weight limit: "+sol.prob.maxWeight);
	}
	
}
